/*
 * Project Name : NOBUNAGA
 * Created on 2007/04/04
 */
package jp.sengoku.oda
{
	import flash.display.DisplayObject;
	import flash.display.Shape;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.charts.HitData;
	import mx.charts.chartClasses.PolarChart;
	import mx.controls.Label;
	import mx.events.FlexEvent;
	import mx.events.ResizeEvent;
	import mx.controls.TextArea;
	import mx.charts.events.ChartItemEvent;
	import mx.charts.chartClasses.AxisBase;
	import mx.charts.LinearAxis;

//	import mx.charts.chartClasses.ChartElement;
//	import mx.events.StateChangeEvent;
//	import mx.effects.Resize;
//	import flash.text.StaticText;
//	import flash.text.TextField;
//	import mx.charts.CategoryAxis;
//	import mx.charts.PieChart;


	/** レーダチャート
	 * ベータ版
	 * ・以降各プロパティ実装予定
	 * @author u102379@gmail.com
	 */
	public class TakigawaChart extends PolarChart
	{
		//チャート軸のカテゴリ名を示すdataProviderのフィールド名
        public var categoryField:String;
				
		//チャート軸のオブジェクト axis
        public var axisLine:Array = new Array();

		//チャート軸のオブジェクト backgraundElements?
        private var chartBaseLine:Array = new Array();

		//チャート軸のテキストオブジェクト
        private var chartBaseLineText:Array = new Array();

		[Bindable]
		//軸の次元数指定（デフォルト：要素の次元数）
		public var NumberOfDimension:Number = -1;

		[Bindable]
		//軸の色（デフォルト：赤）
		public var DimensionLineColor:uint = 0xFF0000;

		//チャート軸、1軸ごとの角度
		public var unitAngle:Number;

		[Bindable]
		//チャート軸の基本の長さ（チャートの大きさとの倍率を指定）（デフォルト：3/8）
		public var DimensionBarRate:Number = 3/8;

		[Bindable]
		//チャート軸の幅（デフォルト：2）
		public var DimensionLineWidth:Number = 2;

		//チャート軸の長さ
		public var dimensionBarLength:Number;
		
		//要素の最大値（Dimensionクラスに移管予定）
		private var dimensionBarMaxValue:Number = 100;
		
		//中心座標
		private var rootPoint:Point;

    	/** コンストラクタでござる
		 */
		public function TakigawaChart() {
			super();

			//描画タイミングをイベントに指定
			this.addEventListener(FlexEvent.CREATION_COMPLETE, _reDrow);
			this.addEventListener(ResizeEvent.RESIZE, _reDrow);
			this.addEventListener(MouseEvent.CLICK, _clickHandler);

			
/*var testObj:Object = getStyle("dataTipRenderer");
var testText:TextArea = new TextArea();
			setStyle("dataTipRenderer",testText);
testObj = getStyle("dataTipRenderer");
*/
			dataTipFunction = dataTipFunction2;
		}

		/** 再描画イベントハンドラ
		 * 各チャートオブジェクト（描画軸、要素）の定義を再計算する。
		 * @param  event
		 * @return void
		 */
		private function _reDrow(event:Object):void{
			//設定値から、必要データの計算を行う
			createChartData();

			//すでに座標軸が描画されている場合は、削除する。
			if(chartBaseLine[0] != null && chartBaseLine[0].parent == this)
				removeChartObject();

			//チャート軸の作成
			createChartBar();

			//チャート要素の作成
			createChartElement();
		}
		

		/** データからグローバル座標を算出する
		 * ローカル座標の中心から、角度・距離を引数にして、グローバル座標を算出する。
		 * @param  ... dataValues	データ（dataValues[0]DataNo,dataValues[1]放射軸）
		 * @return Point			グローバル座標
		 */
		public function dataToGlobal(... dataValues):Point{
			var globalPoint:Point = new Point(0,0);
			var dataValue:Number;
			var radian:Number =  unitAngle * dataValues[0];
			var dimensionBarMaxValue:Number = getAxisObjById(axisLine, dataProvider[dataValues[0]]).maximum;

			if(dimensionBarMaxValue==0)
				dataValue=0;
			else
				dataValue = dimensionBarLength * dataValues[1] / dimensionBarMaxValue;
			
			globalPoint.x = Math.sin(radian) * dataValue + width/2;
			globalPoint.y = - Math.cos(radian) * dataValue + height/2;
			return globalPoint;
		}




		/** ランダムに色情報を取得する（引数と紐付ける）
		 * @param  n	色情報を選択するための数値(整数)
		 * @return uint	色情報
		 */
		private function getRandomColor(n:Number):uint{
			
			var elementColors:Array = new Array();
			elementColors.push(0x00FF00);
			elementColors.push(0x0000FF);
			elementColors.push(0xFFFF00);
			elementColors.push(0xFF00FF);
			elementColors.push(0x00FFFF);
			
			var m:Number = n % elementColors.length;
			
			return elementColors[m];
		}
		
		/** チャートオブジェクトの削除を行う。
		 * @return void
		 */
		private function removeChartObject():void{
			//チャート軸オブジェクトの削除
			for(var i:Number=0; i<chartBaseLine.length; i++){
				removeChild(chartBaseLine[i]);
				chartBaseLine[i] = null;
			}
			chartBaseLine = null;
			chartBaseLine = new Array();

			//チャート軸テキストオブジェクトの削除
			for(i=0; i<chartBaseLineText.length; i++){
				this.removeChild(chartBaseLineText[i]);
				chartBaseLineText[i] = null;
			}
			chartBaseLineText = null;
			chartBaseLineText = new Array();

			//チャート要素オブジェクトの削除（series側）
			for(i=0; i< series.length; i++)
				series[i].removeSeriesElement();

		}
		

		/** 設定値（プロパティ等）からチャートデータの計算を行う
		 */
		private function createChartData():void{
			//チャートの次元数（軸の数）の設定
			if(NumberOfDimension < 0 || dataProvider.length < NumberOfDimension )
				NumberOfDimension = dataProvider.length;

			//チャート軸、1軸ごとの角度の計算
			unitAngle = 2*Math.PI/NumberOfDimension;

			//中心座標
			rootPoint = dataToGlobal(0,0);
			
			//チャート軸の長さ（デフォルト：チャートの大きさ*3/8）
			if( width < height)
				dimensionBarLength = width*DimensionBarRate;
			else
				dimensionBarLength = height*DimensionBarRate;
		}
		
		/** チャート軸の作成
		 * @return void
		 */ 		
		private function createChartBar():void{
			var points:Point;
			var axisObj:Object;

			for(var i:Number=0;i<NumberOfDimension;i++){
				//軸の作成：軸のレンダリング方法（対象オブジェクト）を考察調査する必要あり
				chartBaseLine.push(new Shape());
				axisObj = getAxisObjById(axisLine, dataProvider[i]);

				points = dataToGlobal(i, axisObj.maximum);
				chartBaseLine[i].graphics.lineStyle(DimensionLineWidth,DimensionLineColor,1);
				chartBaseLine[i].graphics.moveTo(rootPoint.x, rootPoint.y);
				chartBaseLine[i].graphics.lineTo(points.x, points.y);
				addChildAt(chartBaseLine[i],0);

//				backgroundElements.push(new ChartElement());
//				backgroundElements[i].graphics.lineStyle(DimensionLineWidth,DimensionLineColor,1);
//				backgroundElements[i].graphics.moveTo(rootPoint.x, rootPoint.y);
//				backgroundElements[i].graphics.lineTo(points.x, points.y);
//				addChildAt(backgroundElements[i],0);

				//ラベルの作成
				chartBaseLineText.push(new Label());
				chartBaseLineText[i].text = axisObj.displayName;
				points = dataToGlobal(i, axisObj.maximum*1.2);
				chartBaseLineText[i].validateNow();
				chartBaseLineText[i].x = points.x;
				chartBaseLineText[i].y = points.y;
				chartBaseLineText[i].setStyle("fontSize",10);
				chartBaseLineText[i].width = 100;
				chartBaseLineText[i].height = 50;

				addChild(chartBaseLineText[i]);
			}
			
		}

		/** Array配列内のオブジェクト（LinearAxis型）から引数で与えられたデータに対応する軸を返す。
		 * 引数に与えられたArray配列内のオブジェクト（LinearAxis型）に対応する軸が存在しない場合は、
		 * 適当な軸オブジェクトを作成し返す。
		 * @param arrayData			対象の配列オブジェクト（軸）（LinearAxis型）
		 * @param dataProviderObj	対象のデータ
		 * @return 					引数（dataProviderObj）に対応する軸（LinearAxis型）
		 */
		private function getAxisObjById(arrayData:Array, dataProviderObj:Object):Object{
			var axisObj:Object = getArrayObjById(arrayData, dataProviderObj[categoryField]);
			
			if(axisObj == null ){
				axisObj = new LinearAxis();
			}
			
			if( axisObj.title == ""){
				axisObj.title = dataProviderObj[categoryField];
			}
			if( axisObj.displayName == ""){
				axisObj.displayName = dataProviderObj[categoryField];
			}
			if( isNaN(axisObj.minimum) ){
				axisObj.minimum = 0;
			}
			if( isNaN(axisObj.maximum)){
				var maxValue:Number = 1;
				for(var i:Number=0; i < series.length; i++){
					if( maxValue < dataProviderObj[series[i].field])
						maxValue = dataProviderObj[series[i].field];
				}
				axisObj.maximum = maxValue;
			}
			
			return axisObj;
		}

		/**Array配列内のオブジェクトから引数で与えられた文字列をIDに持つものを取得する。
		 * @param arrayData	対象の配列
		 * @param keyId		検索対象のID
		 * @return 			検索結果（オブジェクト）
		 */		 
		private function getArrayObjById(arrayData:Array, keyId:String):Object{
			for(var i:Number=0; i < arrayData.length; i++){
				if(arrayData[i].title == keyId)
					return arrayData[i];
			}
			return null;
		}

		
		/** チャート要素の作成
		 * @return void
		 */ 		
		private function createChartElement():void{
			for(var i:Number=0; i< series.length; i++){
				series[i].createChartElement();
			}
		}
		
		/** 指定されたデータのグローバル座標を返す
		 * @param seriesIndex		要素の対象インデックス
		 * @param dataProviderIndex	データプロバイダの対象インデックス
		 */
		private function getDataPoint(seriesIndex:Number, dataProviderIndex:Number):Point{
			//要素名
			var seriesName:String = series[seriesIndex].field;

			if(dataProvider[dataProviderIndex].hasOwnProperty(seriesName)==true){
				//要素データ
				var dataValue:Number = Number(dataProvider[dataProviderIndex][seriesName]);
				return dataToGlobal(dataProviderIndex, dataValue);
			}else{
				return dataToGlobal(0, 0);
			}

		}
		
		/** マウスクリックイベントハンドラ
		 * クリックされたオブジェクト(要素)を最前面に移動する
		 * @param  event
		 */
		private function _clickHandler(event:MouseEvent):void{
			var obj:DisplayObject=null;
			for(var i:Number=0; i < _seriesFilterer.numChildren; i++){
				obj = _seriesFilterer.getChildAt(i);
				if( obj.hitTestPoint(event.stageX, event.stageY, true) == true){
					_seriesFilterer.removeChild(obj);
					_seriesFilterer.addChild(obj);
					i = _seriesFilterer.numChildren;
				}
			}
		}

		/** マウスポインタから最も近いデータポイントが変わったとき
		 */
		private function dataTipFunction2(hit:HitData):String{
			var hintText:String;


			var tSeries:TakigawaSeries = hit.element.parent as TakigawaSeries
			hintText =	tSeries.displayName
						+ "\n  項目は" + hit.item[categoryField]
						+ "\n  値は" + hit.item[tSeries.name];
						
						
						
			return hintText;

		}




	}
}





